﻿using System;
using System.Text;
using System.Windows.Forms;
using Google.GData.Apps;
using Google.GData.Client;
using Microsoft.ManagementConsole;
using Microsoft.ManagementConsole.Advanced;

namespace Google.Apps.MMC
    {
    
    [SnapInSettings("{54C812E1-176E-4444-9DA2-BD8CC6235F5B}",
       DisplayName = "Google Apps Manager",
       Description = "Manage your Google Apps hosted domain user accounts, groups, shared contacts, documents, spreadsheets and calendar events.",
       Vendor = "mattwilko.com")]
    [SnapInAbout("gappsmmc.dll",
        IconId = 1,
        SmallFolderBitmapId= 101,
        LargeFolderBitmapId= 101,
        VersionId = 101)]
    public class GoogleAppsSnapIn : SnapIn
        {

        internal string domain;
        internal string username;
        private string password;

        internal static AppsService appservice;

        internal bool isInitialised = false;

        public GoogleAppsSnapIn()
            {
            this.RootNode = new Root.RootNode();


            AddImage(Properties.Resources.user);
            AddImage(Properties.Resources.group);
            AddImage(Properties.Resources.key);
            AddImage(Properties.Resources.user_red);
            AddImage(Properties.Resources.user_green);
            AddImage(Properties.Resources.new_user);
            AddImage(Properties.Resources.reset_password);
            AddImage(Properties.Resources.new_group);
            AddImage(Properties.Resources.user_admin);
            AddImage(Properties.Resources.googleapps.ToBitmap());

            }

        internal const int icon_user = 0;
        internal const int icon_group = 1;
        internal const int icon_key = 2;
        internal const int icon_suspend = 3;
        internal const int icon_unsuspend = 4;
        internal const int icon_new_user = 5;
        internal const int icon_resetpassword = 6;
        internal const int icon_new_group = 7;
        internal const int icon_user_normal = 0;
        internal const int icon_user_suspended = 3;
        internal const int icon_user_admin = 8;
        internal const int icon_user_noterms = 3;
        internal const int icon_googleappsicon = 9;


        internal bool InitilizationWizard(bool startup)
            {
            LoginForm wizard = new LoginForm();
            if (this.Console.ShowDialog(wizard) == System.Windows.Forms.DialogResult.OK)
                {
                this.domain = wizard.domain.Text;
                this.username = wizard.username.Text;
                this.password = wizard.password.Text;
                appservice = new AppsService(this.domain, this.username + "@" + this.domain, this.password);
                bool retry = true;
                while (retry)
                    {
                    retry = false;
                    try
                        {
                        appservice.RetrieveUser(this.username);
                        }
                    catch (InvalidCredentialsException)
                        {
                        MessageBoxParameters msgbox = new MessageBoxParameters();
                        msgbox.Buttons = MessageBoxButtons.OK;
                        msgbox.Icon = MessageBoxIcon.Error;
                        msgbox.Caption = "Failed to login";
                        msgbox.Text = "Could not login to Google Apps with the credentials provided.";
                        Console.ShowDialog(msgbox);
                        return false;
                        }
                    catch (GDataRequestException e)
                        {
                        System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                        MessageBoxParameters msgbox = new MessageBoxParameters();
                        msgbox.Buttons = MessageBoxButtons.OK;
                        msgbox.Icon = MessageBoxIcon.Error;
                        msgbox.Caption = "Failed to login";
                        if (innere.Status == System.Net.WebExceptionStatus.ProtocolError)
                            {
                            msgbox.Text = "Either the credentials you provided are not authorised to perform administrative tasks, or the domain provided is not a Premier or Education Edition domain.";
                            Console.ShowDialog(msgbox);
                            return false;
                            }
                        else
                            {
                            msgbox.Buttons = MessageBoxButtons.RetryCancel;
                            msgbox.Text = "Could not connect to Google Apps. Please make sure that you are connected to the internet, and try again.";
                            if (Console.ShowDialog(msgbox) == DialogResult.Retry)
                                {
                                retry = true;
                                }
                            }
                        }
                    }
                this.RootNode.DisplayName = appservice.Domain;
                if (startup)
                    {
                    InitializeNodes();
                    }
                this.IsModified = true;
                this.isInitialised = true;
                return true;
                }
            else
                {
                return false;
                }
            }

        protected override void OnLoadCustomData(AsyncStatus status, byte[] persistenceData)
            {
            string data = Encoding.Unicode.GetString(persistenceData);
            string[] strings = data.Split(new string[] { "|" }, 3, StringSplitOptions.RemoveEmptyEntries);
            this.domain = strings[0];
            this.username = strings[1];
            this.password = strings[2];
            appservice = new AppsService(this.domain, this.username + "@" + this.domain, this.password);
            this.RootNode.DisplayName = this.domain;
            this.isInitialised = true;
            this.IsModified = false;
            InitializeNodes();
            }

        protected override byte[] OnSaveCustomData(SyncStatus status)
            {
            string data = this.domain + "|" + this.username + "|" + this.password;
            return Encoding.Unicode.GetBytes(data);
            }


        internal void InitializeNodes()
            {
            // Create "Users" node
            ScopeNode usernode = new CustomNode();

            usernode.ImageIndex = icon_user;
            usernode.SelectedImageIndex = icon_user;
            usernode.DisplayName = "Users";

            MmcListViewDescription user_lvd = new MmcListViewDescription();
            user_lvd.DisplayName = "Users";
            user_lvd.ViewType = typeof(Users.UserListView);
            user_lvd.Options = MmcListViewOptions.ExcludeScopeNodes | MmcListViewOptions.SingleSelect;

            usernode.ViewDescriptions.Add(user_lvd);


            this.RootNode.Children.Add(usernode);

            // Create "Groups" node
            /*ScopeNode groupsnode = new CustomNode();

            groupsnode.ImageIndex = icon_group;
            groupsnode.SelectedImageIndex = icon_group;
            groupsnode.DisplayName = "Groups";

            this.RootNode.Children.Add(groupsnode);*/
            }


        protected override bool OnShowInitializationWizard()
            {
                return InitilizationWizard(true);
            }

        private void AddImage(System.Drawing.Image image)
            {
            this.SmallImages.Add(image);
            this.LargeImages.Add(image);
            }


        internal void ConnectError()
            {
            //this.RootNode = new ScopeNode();
            MessageViewDescription mvd = new MessageViewDescription("Connection Error", "Google Apps Manager could not connect to the internet or could not resolve Google Apps. Please reload the snapin or restart the console to try again.", MessageViewIcon.Error);
            mvd.DisplayName = "Connection Error";
            this.RootNode.ViewDescriptions.Add(mvd);
            this.RootNode.DisplayName = "Google Apps Manager";
            this.RootNode.Children.Clear();
            this.RootNode.ActionsPaneItems.Clear();
            this.RootNode.EnabledStandardVerbs = StandardVerbs.None;
            }

        }
    }
